﻿using System;
using System.IO;
using System.Net;
using nyxwin.Data.Session;
using nyxwin.Data.Utils;
using System.Net.NetworkInformation;
using nyxwin.Common.Resources;

namespace nyxwin.Data.Base
{
    public class RemoteBase
    {
        #region Properties

        public string AuthorizationNick { get; private set; }
        public string AuthorizationToken { get; private set; }

        #endregion

        #region Events

        public event EventHandler<ErrorOccurredEventArgs> ErrorOccurred;
        protected event EventHandler<InvocationEventArgs> InvocationCompleted;

        #endregion

        #region Construction

        protected RemoteBase(string authorizationNick, string authorizationToken)
        {
            AuthorizationNick = authorizationNick;
            AuthorizationToken = authorizationToken;
        }

        #endregion

        #region InvokeRemote

        protected void InvokeRemote(string method, string parameter, /*params*/ string[] otherArguments)
        {
            InvokeRemote(method, parameter, otherArguments, null);
        }

        protected void InvokeRemote(string method, string parameter, /*params*/ string[] otherArguments, object state)
        {
            if (!NetworkInterface.GetIsNetworkAvailable())
            {
                FireErrorOccurred(new ErrorOccurredEventArgs(ErrorResource.NoConnectionAvailable));
            }

            try
            {
                var request = WebRequest.CreateHttp(LoginManager.ApiUri);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.UserAgent = UserDeviceIdentity.UserAgent;
                request.Headers["referer"] = "http://www.nyx.cz/api.php";

                request.BeginGetRequestStream(
                    delegate(IAsyncResult asyncResultStream)
                    {
                        try
                        {
                            Stream stream = request.EndGetRequestStream(asyncResultStream);
                            using (var streamWr = new StreamWriter(stream))
                            {
                                string str = string.Format("auth_nick={3}&auth_token={4}&l={0}&l2={1}{2}",
                                                                                     method, parameter,
                                                                                     (otherArguments == null || otherArguments.Length == 0) ? "" : "&" + string.Join("&", otherArguments),
                                                                                     AuthorizationNick, AuthorizationToken);

                                streamWr.Write(str);
                            }

                            request.BeginGetResponse(
                                delegate(IAsyncResult asyncResultResponse)
                                {
                                    var data = "";
                                    try
                                    {
                                        using (var webResponse = request.EndGetResponse(asyncResultResponse))
                                        {
                                            var response = webResponse as HttpWebResponse;

                                            using (var streamRd = new StreamReader(response.GetResponseStream()))
                                                data = streamRd.ReadToEnd();

                                            if (string.IsNullOrEmpty(data) || data.Contains("Not Authorized"))
                                            {
                                                FireErrorOccurred(new ErrorOccurredEventArgs(ErrorResource.NotAuthorized));
                                            }
                                            else
                                            {
                                                FireInvocationCompleted(new InvocationEventArgs { Method = method, Parameter = parameter, OtherArguments = otherArguments, Result = data, State = state });
                                            }
                                        }
                                    }
                                    catch (Exception)
                                    {
                                        FireErrorOccurred(new ErrorOccurredEventArgs(ErrorResource.ConnectionFailed));
                                    }
                                },
                                null);
                        }
                        catch (Exception)
                        {
                            FireErrorOccurred(new ErrorOccurredEventArgs(ErrorResource.ConnectionFailed));
                        }

                    },
                    null);
            }
            catch (Exception ex)
            {
                FireErrorOccurred(new ErrorOccurredEventArgs(ex)
                                                    {
                                                        Error = true,
                                                        ErrorMessage = ex.Message
                                                    });
            }
        }

        #endregion

        #region FireErrorOccurred

        protected void FireErrorOccurred(ErrorOccurredEventArgs e)
        {
            if (null != ErrorOccurred)
            {
                ErrorOccurred(this, e);
            }
            else
            {
                throw new ArgumentNullException(
                    string.Format("Unhandled 'ErrorOccurred' event handler, got error: {0}", e.ErrorMessage));
            }
        }

        #endregion

        #region FireInvocationCompleted

        private void FireInvocationCompleted(InvocationEventArgs e)
        {
            if (null != InvocationCompleted)
            {
                InvocationCompleted(this, e);
            }
        }

        #endregion
    }
}